/*
* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class CanvasInput_ {//输入框
    // static Reset(x, y, w, h, value, cb) {
    //     let ci = document.getElementById("canvas_input");
    //     ci.type = "text";//"number"
    //     ci.style.left = x + "px";
    //     ci.style.top = y + "px";
    //     ci.style.width = w + "px";
    //     ci.style.height = h + "px";
    //     ci.value = value;
    //     ci.onchange = (e) => {
    //         cb(e.target.value);
    //     }
    //     ci.focus();
    // }
    // static Hide() {
    //     let ci = document.getElementById("canvas_input");
    //     ci.type = "hidden";
    // }
    static INPUT_PROC = null;
    static Reset(x, y, w, h, value, cb, endcb = null) {
        let ci = document.getElementById("canvas_textarea");
        ci.style.left = x + "px";
        ci.style.top = y + "px";
        ci.style.width = w + "px";
        ci.style.height = h + "px";
        ci.style.display = "block";
        ci.value = value;
        ci.onchange = (e) => {
            if (this.INPUT_PROC) {
                this.INPUT_PROC.value = e.target.value;
            }
            if (!endcb) cb(e.target.value);
        }
        ci.focus();

        ci.onkeydown = (k) => {
            if (k.key == "Enter") {
                if (k.shiftKey) {
                }
                else {
                    CanvasInput_.Hide();
                }
            }
        };
        ci.onkeyup = (e) => {
            if (this.INPUT_PROC) {
                this.INPUT_PROC.value = e.target.value;
            }
            if (!endcb) cb(e.target.value);
        };
        this.INPUT_PROC = {
            cb: cb,
            endcb: endcb,
            value: value,
        }
    }
    static Hide() {
        let ci = document.getElementById("canvas_textarea");
        ci.style.display = "none";

        const { GLFrame } = require("../engine/GLFrame");
        GLFrame.gi().cvs_.focus();
        if (this.INPUT_PROC && this.INPUT_PROC.endcb) {
            this.INPUT_PROC.endcb(this.INPUT_PROC.value);
        }
        this.INPUT_PROC = null;
    }
}

const { updateInputClass } = require("../engine/XTextInput");
const { XTools } = require("../engine/XTools");

class MonacoInput_ {
    static INPUT_PROC = null;
    static EXTRA_LIB = null;
    static generateFunctionSignature(fn) {
        // 获取函数的参数和返回值类型
        let abc = fn.toString();
        const args = fn.toString().match(/\(([^)]*)\)/)[1]; // 提取参数部分
        // const returnType = typeof fn(); // 获取返回值类型
        const returnType = "any"; // 目前暂时不支持函数返回值

        // 将参数转换为 TypeScript 参数类型，可能存在预设参数值
        const params = args
            .split(",")
            .map((arg) => arg.trim())
            .filter((arg) => arg) // 过滤空参数
            .map((arg) => {
                const [name, defaultValue] = arg.split("=");
                // if (defaultValue) {
                //     return `${name}: ${typeof defaultValue}`;
                // } else {
                return `${name}: any`;
                // }
            })
            .join(", ");

        return `(${params}) => ${returnType}`;
    }
    static generateTypeDefinition(obj) {
        let result = `{\n`;

        for (const key in obj) {
            if (!XTools.isValidVariableName(key)) {
                continue;
            }
            if (obj.hasOwnProperty(key)) {
                const value = obj[key];
                const type = typeof value;
                // console.log("generateTypeDefinition key=", key);
                if (type === "object" && !Array.isArray(value) && value !== null) {
                    // 处理嵌套对象
                    result += `    ${key}: ${this.generateTypeDefinition(value, key)};\n`;
                } else if (Array.isArray(value)) {
                    // 处理数组
                    const arrayType = value.length > 0 ? typeof value[0] : "any";
                    result += `    ${key}: ${arrayType}[];\n`;
                } else if (type === "function") {
                    // 处理函数
                    result += `    ${key}: ${this.generateFunctionSignature(value)};\n`;
                } else {
                    // 处理基本类型
                    result += `    ${key}: ${type};\n`;
                }
            }
        }

        result += "}";
        return result;
    }
    static updateExtraLib(s) {
        if (this.EXTRA_LIB) {
            this.EXTRA_LIB.dispose();
        }
        if (!s) {
            s = ""
            if ("X" in window) {
                s += "declare const X: " + this.generateTypeDefinition(X);
            }
            if ("N" in window && N != null) {
                s += "declare const N: " + this.generateTypeDefinition(N);
            }
        }
        if (!s) {
            return;
        }
        // 将类型定义加载到 Monaco Editor
        // console.log(s);
        this.EXTRA_LIB = monaco.languages.typescript.javascriptDefaults.addExtraLib(
            s,
            'x.d.ts' // 文件名
        );
        console.log("extra lib updated");
    }
    static openReplace(s1, s2) {
        // 打开替换框
        this.EDITOR.trigger("keyboard", "editor.action.startFindReplaceAction");

        // 获取查找替换的贡献
        const findController = this.EDITOR.getContribution("editor.contrib.findController");
        if (findController) {
            // 设置搜索文本
            findController.getState().change({
                searchString: s1, // 搜索文本
                replaceString: s2, // 替换文本
            }, false); // 第二个参数 false 表示不重置历史记录
        }
    }
    static IsOn() {
        return this.INPUT_PROC;
    }
    static CURRENT_LANGUAGE = "javascript";
    static Reset(options) {
        this.DIV.style.position = "absolute";
        this.DIV.style.left = options.x + "px";
        this.DIV.style.top = options.y + "px";
        this.DIV.style.width = options.w + "px";
        this.DIV.style.height = options.h + "px";
        this.DIV.style.display = "block";
        let setLanguage = "javascript";
        if (options.language) {
            setLanguage = options.language;
        }
        if (setLanguage != this.CURRENT_LANGUAGE) {
            monaco.editor.setModelLanguage(this.EDITOR.getModel(), setLanguage);
            this.CURRENT_LANGUAGE = setLanguage;
        }

        this.EDITOR.layout();
        this.INPUT_PROC = options;
        this.EDITOR.setValue(options.defaultValue);
        this.EDITOR.focus();
    }
    static Hide() {
        this.DIV.style.display = "none";

        const { GLFrame } = require("../engine/GLFrame");
        GLFrame.gi().cvs_.focus();
        if (this.INPUT_PROC && this.INPUT_PROC.onFinish) {
            let ret = this.EDITOR.getValue();
            if (this.INPUT_PROC.defaultValue != ret) {
                this.INPUT_PROC.onFinish(ret);
            }
        }
        this.INPUT_PROC = null;
    }
    static Init() {
        setTimeout(() => {
            if (window.monaco != undefined) {
                console.log("monaco inited");
                this.DIV = document.getElementById("container_monaco");
                this.EDITOR = monaco.editor.create(this.DIV, {
                    value: "",
                    language: "javascript",
                    // automaticLayout: true,
                    theme: 'vs-dark',
                    // fontSize: 14,
                    readOnly: false,
                    // formatOnType: true,
                    // formatOnPaste: true,
                });
                this.EDITOR.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, function () {
                    this.Hide();
                });
                // this.updateExtraLib();
                this.DIV.style.display = "none";

                // MonacoInput_.INLINE_SUGGESTION_STATUS = 0;
                // this.EDITOR.addCommand(monaco.KeyCode.F4, function () {
                //     if (MonacoInput_.INLINE_SUGGESTION_STATUS == 0) {
                //         MonacoInput_.INLINE_SUGGESTION_STATUS = 1;
                //         MonacoInput_.EDITOR.trigger('custom', 'editor.action.inlineSuggest.trigger');
                //     }
                // });

                // monaco.languages.registerInlineCompletionsProvider('javascript', {
                //     provideInlineCompletions: (model, position, context, token) => {
                //         if (MonacoInput_.INLINE_SUGGESTION_STATUS != 1) {
                //             return;
                //         }
                //         if (token.isCancellationRequested) {
                //             MonacoInput_.INLINE_SUGGESTION_STATUS = 0;
                //             return { items: [] };
                //         }
                //         token.onCancellationRequested(() => {
                //             console.log("onCancellationRequested");
                //         });
                //         MonacoInput_.INLINE_SUGGESTION_STATUS = 2;
                //         let line_start = Math.max(position.lineNumber - 5, 1);
                //         let line_end = Math.min(position.lineNumber + 5, model.getLineCount());
                //         line_start = 1;
                //         line_end = model.getLineCount();
                //         let str_before = "";
                //         for (let l = line_start; l < position.lineNumber; l++) {
                //             str_before += model.getLineContent(l) + "\n";
                //         }
                //         str_before += model.getLineContent(position.lineNumber).substring(0, position.column - 1);
                //         let str_after = model.getLineContent(position.lineNumber).substring(position.column - 1);
                //         for (let l = position.lineNumber + 1; l <= line_end; l++) {
                //             str_after += "\n" + model.getLineContent(l);
                //         }
                //         const range = {
                //             startLineNumber: position.lineNumber,
                //             endLineNumber: position.lineNumber,
                //             startColumn: position.column,
                //             endColumn: position.column,
                //         };
                //         console.log("!!!!!!!!!!!!!!!!!!!!!");
                //         MonacoInput_.INLINE_SUGGESTION_STATUS = 0;
                //         return new Promise((resolve, reject) => {
                //             fetch('http://ccnto.x3322.net:6789/ai', {
                //                 method: 'POST',
                //                 headers: {
                //                     'Content-Type': 'application/json'
                //                 },
                //                 body: JSON.stringify({
                //                     "method": "fim",
                //                     "prefix": str_before,
                //                     "suffix": str_after
                //                 })
                //             })
                //                 .then(response => response.json())
                //                 .then(data => {
                //                     console.log('Success:', data);
                //                     if (data.status == 1) {
                //                         let ret = {
                //                             items: [
                //                                 {
                //                                     text: data.data,
                //                                     range: range,
                //                                     insertText: data.data,
                //                                 }
                //                             ],
                //                         };
                //                         console.log("return ret", ret);
                //                         if (token.isCancellationRequested) {
                //                             resolve({ items: [] });
                //                         } else {
                //                             resolve(ret);
                //                         }
                //                     }
                //                 })
                //                 .catch((error) => {
                //                     reject(error);
                //                 });
                //         });
                //     },
                //     freeInlineCompletions: () => {
                //     },
                // });
            }
            else {
                console.log("monaco not inited, retry");
                MonacoInput_.Init();
            }
        }, 300);
    }
}

MonacoInput_.Init();

updateInputClass(CanvasInput_, MonacoInput_);
